#include <iostream>
#include <string>
#include <vector>
#include <boost/filesystem.hpp>
#include "Util.hpp"
const std::string _src_path = "data/input";
const std::string output = "data/raw_html/raw.txt";

typedef struct EleInfo
{
    std::string _title;   // 每个html文件的标题
    std::string _content; // 每个html文件的摘要
    std::string _url;     // 每个html的url
} EleInfo_t;

// 保存所有的html文件路径 + 文件名字
bool EnumAllFiles(const std::string &_src_path, std::vector<std::string> *_files_list)
{
    boost::filesystem::path _root_path(_src_path);
    if (!boost::filesystem::exists(_root_path))
    {
        return false;
    }
    boost::filesystem::recursive_directory_iterator end;
    for (boost::filesystem::recursive_directory_iterator iter(_root_path); iter != end; iter++)
    {
        if (!boost::filesystem::is_regular_file(iter->path())) // 不是普通文件 跳过
            continue;
        if (iter->path().extension() != ".html") // 文件后缀不是.html 跳过
            continue;
        //        std::cout << iter->path().string() << std::endl;
        _files_list->push_back(iter->path().string());
    }

    return true;
}

bool ParseTitle(const std::string &_ret, std::string *out)
{
    std::string _key1 = "<title>";
    auto it1 = _ret.find(_key1);

    if (it1 == std::string::npos)
    {
        return false;
    }

    auto it2 = _ret.find("</title>");
    if (it2 == std::string::npos)
    {
        return false;
    }

    it1 += _key1.size();
    if (it1 > it2)
    {
        return false;
    }
    *out = _ret.substr(it1, it2 - it1);

    return true;
}

bool ParseContent(const std::string &_ret, std::string *out)
{
    enum Status
    {
        LABLE,
        CONTENT
    };

    Status _s = LABLE;
    for (char c : _ret)
    {
        switch (_s)
        {
        case LABLE:
            if (c == '>')
                _s = CONTENT;
            break;
        case CONTENT:
            if (c == '<')
                _s = LABLE;
            else
            {
                out->push_back(c);
            }
            break;
        }
    }
    return true;
}

bool ParseUrl(const std::string &file_path, std::string *out)
{
    // file_path: "data/input/a.html"
    std::string _url_head = "https://www.boost.org/doc/libs/1_78_0/doc/html";
    size_t pos = file_path.rfind("/");
    if (pos == std::string::npos)
    {
        return false;
    }
    std::string _url_tail = file_path.substr(pos);
    *out = _url_head + _url_tail;

    return true;
}

// 将所有html的文件中的EleInfo信息提取出来放入_results中
bool ParserTheHtml(std::vector<std::string> &_files_list, std::vector<EleInfo_t> *_results)
{
    for (auto &file : _files_list)
    {
        std::string _ret;
        EleInfo_t filemessage;

        if (!Util::FileUtil::ReadFile(file, &_ret))
        {
            std::cout << "Read file error!" << std::endl;
            continue;
        }

        if (!ParseTitle(_ret, &filemessage._title))
        {
            std::cout << "parse title error!" << std::endl;
            continue;
        }

        if (!ParseContent(_ret, &filemessage._content))
        {
            std::cout << "parse content error!" << std::endl;
            continue;
        }

        if (!ParseUrl(file, &filemessage._url))
        {
            std::cout << "parse url error!" << std::endl;
            continue;
        }

        _results->push_back(std::move(filemessage));
        // for debug
        //  std::cout << "file title: " << filemessage._title << std::endl;
        //  std::cout << "file content: " << filemessage._content << std::endl;
        //  std::cout << "file url: " << filemessage._url << std::endl;
        //  break;
    }

    return true;
}

#define SEP '\3'
// 把_results中所有的去标签化的html信息放入到output中,每两个html用\3隔开
bool SaveAllFiles(std::vector<EleInfo_t> &_results, const std::string &_output)
{
    std::ofstream out(output, std::ios::out | std::ios::binary);
    if(!out.is_open())
    {
        return false;
    }
    
    for(auto& result : _results)
    {
        std::string _message = result._title;
        _message += SEP;
        _message += result._content;
        _message += SEP;
        _message += result._url;
        _message += '\n';
        out.write(_message.c_str(),_message.size());
    }

    out.close();

    return true;
}

int main()
{
    std::vector<std::string> _files_list; // 保存所有的html文件路径 + 文件名字
    if (!EnumAllFiles(_src_path, &_files_list))
    {
        std::cout << "Enum files error!" << std::endl;
        return 1;
    }

    std::vector<EleInfo_t> _results;
    if (!ParserTheHtml(_files_list, &_results)) // 把所有html去标签(数据清洗) 放入到_results中
    {
        std::cout << "Parser files error!" << std::endl;
        return 2;
    }

    if (!SaveAllFiles(_results, output)) // 把_results中所有的去标签化的html信息放入到output中,每两个html用\3隔开
    {
        std::cout << "Save files error!" << std::endl;
        return 3;
    }

    return 0;
}
